package com.usian.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.common.dtos.PageResponseResult;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.media.dtos.WmNewsDto;
import com.usian.model.media.dtos.WmNewsPageReqDto;
import com.usian.model.media.dtos.WmNewsVo;
import com.usian.model.media.pojos.WmMaterial;
import com.usian.model.media.pojos.WmNews;
import com.usian.model.media.pojos.WmNewsMaterial;
import com.usian.model.media.pojos.WmUser;
import com.usian.utils.threadlocal.WmThreadLocalUtils;
import com.usian.wemedia.mapper.WmMaterialMapper;
import com.usian.wemedia.mapper.WmNewsMapper;
import com.usian.wemedia.mapper.WmNewsMaterialMapper;
import com.usian.wemedia.mapper.WmUserMapper;
import com.usian.wemedia.service.WmNewsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Value("${fileServerUrl}")
    private String fileServerUrl;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private KafkaTemplate kafkaTemplate;


    //常量
    public static final Short COLLECT_MATERIAL = 1;//收藏
    public static final Short CANCEL_COLLECT_MATERIAL = 0;//收藏
    public static final String WM_NEWS_TYPE_IMAGE = "image";
    public static final Short WM_NEWS_NONE_IMAGE = 0;
    public static final Short WM_NEWS_SINGLE_IMAGE = 1;
    public static final Short WM_NEWS_MANY_IMAGE = 3;
    public static final Short WM_NEWS_TYPE_AUTO = -1;
    public static final Short WM_CONTENT_REFERENCE = 0;
    public static final Short WM_COVER_REFERENCE = 1;
    public static final short WM_NEWS_CONTENT_REFERENCE = 1;//主图引用


    /*
     * 查询
     * */
    @Override
    public ResponseResult findAll(WmNewsPageReqDto dto) {
        //检查参数
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        //分页参数
        dto.checkParam();
        //分页条件查询
        IPage page = new Page(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<WmNews> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        //关键字模糊查询
        if (dto.getKeyword() != null) {
            lambdaQueryWrapper.like(WmNews::getTitle, dto.getKeyword());
        }
        //状态查询
        if (dto.getStatus() != null) {
            lambdaQueryWrapper.eq(WmNews::getStatus, dto.getStatus());
        }
        //频道查询
        if (dto.getChannelId() != null) {
            lambdaQueryWrapper.eq(WmNews::getChannelId, dto.getChannelId());
        }
        //区间查询
        if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null) {
            lambdaQueryWrapper.between(WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate());
        }
        //查询当前登录用户信息
        WmUser user = WmThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        lambdaQueryWrapper.eq(WmNews::getUserId, user.getId());
        //按照日期倒叙
        lambdaQueryWrapper.orderByDesc(WmNews::getCreatedTime);
        IPage result = page(page, lambdaQueryWrapper);

        //封装返回结果
        PageResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) result.getTotal());
        responseResult.setData(result.getRecords());
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }


        /*
        * 文章发布
        *
        *
        * */

    @Override
    public ResponseResult submitNews(WmNewsDto dto, Short isSubmit) {
        //判断参数
        if (dto == null || StringUtils.isBlank(dto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }

        //0代表草稿 1代表提交审核
        if (isSubmit == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        //2.解析json串 解析主表wmnews
        //保存wmNews表
        WmNews wmNews = new WmNews();
        //对象拷贝 ---深拷贝 浅拷贝 对象把值放到堆中 从源头考到目的地
        BeanUtils.copyProperties(dto, wmNews);
        //封面是自动的，那type赋值为空
        if (WM_NEWS_TYPE_AUTO.equals(dto.getType())) {
            wmNews.setType(null);
        }
        //处理解析封面图片 确保对象不能等于空
        if (dto.getImages() != null && dto.getImages().size() > 0) {
            String replace = dto.getImages().toString().replace("[", "")
                    .replace("]", "")
                    .replace(fileServerUrl, "")
                    .replace(" ", "");
            wmNews.setImages(replace);
        }

        //
        wmNews.setCreatedTime(new Date());

        WmUser user = WmThreadLocalUtils.getUser();
        if (user==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        wmNews.setUserId(user.getId());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short) 1);

        //判断是否是添加还是删除
        if (wmNews.getId()==null){
            //4、保存新闻表
            this.save(wmNews);
        }else {
            this.updateById(wmNews);
            //把素材与文章的关系表删除掉 先删后新增
            QueryWrapper<WmNewsMaterial> queryWrapper=new QueryWrapper<>();
            queryWrapper.lambda().eq(WmNewsMaterial::getNewsId,wmNews.getId());
            wmNewsMaterialMapper.delete(queryWrapper);
        }



        //3.素材表 替换 解析 保存素材表
        String content = dto.getContent();
        //3.1 json转换为一个list集合
        List<Map> list = JSON.parseArray(content, Map.class);

        //3.2、提取内容中的图片
        List<String> ectractUrlInfo = this.ectractUrlInfo(list);

        //3.3、校验内容中的图片是否一致   //4、批量保存关系表
        if (isSubmit.equals(WmNews.Status.SUBMIT.getCode()) && ectractUrlInfo.size() > 0) {

            //调用保存文章和素材的关系表
            ResponseResult result = this.saveRelativeInfoForContent(ectractUrlInfo, wmNews.getId());
            if (result != null) {
                return result;
            }
        }

        //设置封面
        if (isSubmit.equals(WmNews.Status.SUBMIT.getCode())) {
            ResponseResult responseResult = this.saveRelativeInfoForContent(dto, ectractUrlInfo, wmNews);
            if (responseResult!=null){
                return responseResult;
            }
        }
        return null;
    }




    //提取封面图片且维护封面和素材表之间的关系
    private ResponseResult saveRelativeInfoForContent(WmNewsDto dto, List<String> imageList, WmNews wmNews) {
        //1.判断多图 一图 修改主表的字段
        List<String> imageListNew = dto.getImages();
        if (dto.getType().equals(WM_NEWS_TYPE_AUTO)) {
            if (imageList.size() > 0 && imageList.size() <= 2) {
                wmNews.setType(WM_NEWS_SINGLE_IMAGE);
                imageListNew = imageList.stream().limit(1).collect(Collectors.toList());
            } else if (imageList.size() > 2) {
                wmNews.setType(WM_NEWS_MANY_IMAGE);
                imageListNew = imageList.stream().limit(3).collect(Collectors.toList());
            } else {
                wmNews.setType(WM_NEWS_NONE_IMAGE);
            }
        }
        if (imageListNew.size() > 0) {
            wmNews.setImages(imageListNew.toString().replace("[", "")
                    .replace("]", "").replace(fileServerUrl, "")
                    .replace(" ", ""));
        }


        this.updateById(wmNews);

            List<String> imglistNew1=new  ArrayList<>();

        for(String s:imageListNew){

            imglistNew1.add( s.replace(fileServerUrl, ""));
        }

        //2.维护封面图片和素材的关系                                                       文章的Id
        ResponseResult responseResult = this.saveRelativeInfoForContent(imglistNew1, wmNews.getId());
        return  responseResult;
    }



    // 保存素材关系表 至少有两个参数一个是图片的集合 文章的id  =====过滤的是在库中没有的数据
    public  ResponseResult saveRelativeInfoForContent(List<String> imgList,Integer wmNewsId){
        //1、判断提取出来的图片是否存在于素材库中
        LambdaQueryWrapper<WmMaterial> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(WmMaterial::getUrl,imgList);

        WmUser user = WmThreadLocalUtils.getUser();
        if (user==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        lambdaQueryWrapper.eq(WmMaterial::getUserId,user.getId());

        //拿到素材的Mapper 素材的集合
        List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(lambdaQueryWrapper);

        //2：如果存在 二次概率真实存在与素材库的图片提取，存新的集合
        List<String> wmMaterialListNew=new ArrayList<>();
        if (wmMaterials.size()>0){
            //3:构建一个每条数据模型 map集合        key是图片的地址素材的url value是素材ID
            Map<String, Integer> map = wmMaterials.stream().collect(Collectors.toMap(WmMaterial::getUrl, WmMaterial::getId));
            //4：循环wmMaterials来过滤摸鱼的
            for (WmMaterial wmMaterial : wmMaterials) {
                //看他的key能不能拿到值
                Integer wmId = map.get(wmMaterial);
                if (wmId==null){
                    //库中没有
                    return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "应用图片失效");
                }else {
                    //这些都是真实存在的
                    wmMaterialListNew.add(wmId.toString());
                }
            }

        }
        //保存中间表
        wmNewsMaterialMapper.saveRelationsByContent(wmMaterialListNew,wmNewsId,WM_NEWS_CONTENT_REFERENCE);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }





    /*
     * 自定义提取文章内容中的图片
     * */
    public  List<String> ectractUrlInfo(List<Map> maplist){

        List<String> imgList= new ArrayList<>();

        for (Map map : maplist) {
            //判断是不是图片
            if (map.get("type").equals(WM_NEWS_TYPE_IMAGE)){
                String imageUrl= (String) map.get("value");
                imgList.add(imageUrl.replace(fileServerUrl,""));

            }
        }
        return imgList;
    }



    /*
     * 文章删除
     * */
    @Override
    public ResponseResult delNews(Integer id) {
        //判断参数
        if (id==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //获取数据
        WmNews wmNews = getById(id);
        //判断文章是否存在
        if (wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //判断当前文章状态  status==9 enable===1
        if (wmNews.getStatus()!=9 && wmNews.getEnable()==1){

            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST);
        }

        //删除素材与文章的关系
        wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,id));

        //删除文章
        removeById(wmNews.getId());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 文章上下架
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {

        //判断参数
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST);
        }

        //查询文章
        WmNews wmNews = getById(dto.getId());

         //判断文章
         if (wmNews==null){
           return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
          }

         //判断文章是否发布
        if (!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //修改文章状态，同步到app(后期)TODO
        if (dto.getStatus()!=null&&dto.getEnable()>-1 && dto.getEnable()<2){
            update(Wrappers.<WmNews>lambdaUpdate().eq(WmNews::getId,dto.getId()).set(WmNews::getEnable,dto.getEnable()));

            //发kafka消息去通知文章服务上下架文章 生产者 文章微服务消费者
            Map<String,Object> map=new HashMap<>();
            map.put("enable",dto.getEnable());// 0: 上架 1：下架
            map.put("articleId",wmNews.getArticleId());// 0: 上架 1：下架
            kafkaTemplate.send("newsDownOrUp",JSON.toJSONString(map));

        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /*
    * 文章修改
    * */
    @Override
    public ResponseResult findByNewsId(Integer id) {

        if (id==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }


        WmNews wmNews = this.getById(id);

        ResponseResult responseResult = ResponseResult.okResult(wmNews);
        responseResult.setHost(fileServerUrl);
        return  responseResult;
    }




    @Override
    public ResponseResult updateNewStatus(WmNews wmNews) {
        if (wmNews==null && wmNews.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        boolean b = this.updateById(wmNews);

        if (b){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }else {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

    @Override
    public List<Integer> findRelease() {

        // 查询 状态为8的 判断发布时间小于当前时间
        List<WmNews> list = list(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getStatus, 8).lt(WmNews::getPublishTime, new Date()));


        // 转换为集合
        List<Integer> list1 = list.stream().map(WmNews::getId).collect(Collectors.toList());
        return list1;
    }

    /**
     * 查询文章列表
     *
     * @param dto
     * @return
     */
    @Override
    public PageResponseResult findList(NewsAuthDto dto) {


        //检查下参数
        dto.checkParam();

        //设置初始值
        dto.setPage(dto.getPage()-1*dto.getSize());

        //分页查询
        List<WmNewsVo> listAndPage = wmNewsMapper.findListAndPage(dto);

        //统计总共有多少天数据
        int listCount = wmNewsMapper.findListCount(dto);

        //封装结果并返回
        PageResponseResult pageResponseResult=new PageResponseResult(dto.getPage(),dto.getSize(),listCount);
        pageResponseResult.setData(listAndPage);

        return pageResponseResult;
    }

    /**
     * 查询文章详情
     *
     * @param id
     */
    @Override
    public WmNewsVo findWmNewsVo(Integer id) {

        //获取文章的信息
        WmNews wmNews= getById(id);



        //查询作者
        WmUser wmUser=null;

        if (wmNews!=null && wmNews.getUserId()!=null){
            wmUser = wmUserMapper.selectById(wmNews.getId());
        }


        //封装结果信息斌返回

        WmNewsVo wmNewsVo=new WmNewsVo();

        BeanUtils.copyProperties(wmNews,wmNewsVo);

        if (wmUser!=null){
            wmNewsVo.setAuthorName(wmUser.getName());
        }
        return wmNewsVo;
    }
}
